package com.sunlands.deskmate.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 1. storage : 从外部发来的消息最先进入存储序列, 存储成功之后进入下一步:
 * 2. lookup : 进行消息的发布
 * 3. system : 系统消息
 *
 * @author anjunling@sunlands.com
 */

@SuppressWarnings("unused")
@Slf4j
@Data
@Configuration
public class RabbitMqConfig {
    @Value("${spring.profiles.active}")
    private String env;
    /**
     * 从client端发来的消息, 下一步是LOOKUP
     */
    private static final String MQ_PREFIX = "TZ_";

    public static final String EXCHANGE_STORAGE = MQ_PREFIX + "MESSAGE_TO_MQ_EXCHANGE_DIRECT";
    public static final String QUEUE_STORAGE = MQ_PREFIX + "MESSAGE_2_MQ_MSG";
//    private static final String QUEUE_MESSAGE_SUCCESS_2_SALES_WORK_REPORT = "QUEUE_MESSAGE_SUCCESS_2_SALES_WORK_REPORT";
//    private static final String QUEUE_MESSAGE_SUCCESS_2_SALES_QUALITY_CHECK = "QUEUE_MESSAGE_SUCCESS_2_SALES_QUALITY_CHECK";

    /**
     * 从STORAGE发来的消息, 推送到网页
     */
    public static final String EVENT_EXCHANGE_LOOKUP = MQ_PREFIX + "EVENT_TO_MQ_EXCHANGE_FANOUT_LOOKUP";
    public static final String EVENT_QUEUE_LOOKUP = MQ_PREFIX + "EVENT_2_MQ_MSG_LOOKUP";

//    public static final String EXCHANGE_SYSTEM = PREFIX + "EVENT_TO_MQ_EXCHANGE_FANOUT_SYSTEM";
//    public static final String QUEUE_SYSTEM = PREFIX + "EVENT_2_MQ_MSG_SYSTEM";

    /**
     * 消息消费成功，通知history与user服务
     */
    public static final String EXCHANGE_SUCCESS = MQ_PREFIX + "MESSAGE_EXCHANGE_DIRECT";
    public static final String QUEUE_MESSAGE_PERSIST = MQ_PREFIX + "MESSAGE_PERSIST_QUEUE";
//    private static final String QUEUE_MESSAGE_NEWEST = "MESSAGE_NEWEST_QUEUE";

//    public static final String EXCHANGE_CHANNEL_STATUS = PREFIX + "CHANNEL_STATUS_DIRECT";
//    private static final String QUEUE_CHANNEL_STATUS = PREFIX + "CHANNEL_STATUS";


    public static final String EXCHANGE_ERROR_MESSAGE = MQ_PREFIX + "EXCHANGE_ERROR_MESSAGE";
    public static final String QUEUE_ERROR_MESSAGE = MQ_PREFIX + "QUEUE_ERROR_MESSAGE";


    @Configuration
    public static class StorageBindingConfig {

        @Value("${spring.profiles.active}")
        private String env;

        @Bean
        public DirectExchange storageExchange() {
            return new DirectExchange(EXCHANGE_STORAGE, true, false);
        }

        @Bean
        public Queue storageQueue() {
            return new Queue(QUEUE_STORAGE + "_" + env, true);
        }

        @Bean
        public Binding storageBinding() {
            return BindingBuilder.bind(storageQueue())
                    .to(storageExchange()).with(env);
        }

    }
//
//    @Configuration
//    @Data
//    public static class SystemBindingConfig {
//        /**
//         * 在服务器环境变量中配置的workerId, 每个节点应该不同
//         */
//        @Value("${WORKER_ID}")
//        String workerId;
//
//        @Bean
//        public FanoutExchange systemExchange() {
//            return new FanoutExchange(EXCHANGE_SYSTEM, true, false);
//        }
//
//        @Bean
//        public Queue systemQueue() {
//            return new Queue(QUEUE_SYSTEM + workerId, true);
//        }
//
//        @Bean
//        public Binding systemBinding() {
//            return BindingBuilder.bind(systemQueue())
//                    .to(systemExchange());
//        }
//    }


    @Getter
    @Configuration
    public static class LookupBindingConfig {
        /**
         * 在服务器环境变量中配置的workerId, 每个节点应该不同
         */
        @Value("${WORKER_ID}")
        String workerId;

        @Bean
        public Queue lookupQueue() {
            return new Queue(EVENT_QUEUE_LOOKUP + workerId, true);
        }


        @Bean
        public DirectExchange lookupExchange() {
            return new DirectExchange(EVENT_EXCHANGE_LOOKUP, true, false);
        }


        @Bean
        public Binding lookupBinding() {
            return BindingBuilder.bind(lookupQueue())
                    .to(lookupExchange()).with(workerId);
        }


    }

//    @Configuration
//    public static class ChannelStatusBindingConfig {
//
//        @Value("${spring.profiles.active}")
//        private String env;
//
//        @Bean
//        public Queue channelStatusQueue() {
//            return new Queue(QUEUE_CHANNEL_STATUS + "_" + env, true);
//        }
//
//        @Bean
//        public DirectExchange channelStatusExchange() {
//            return new DirectExchange(EXCHANGE_CHANNEL_STATUS, true, false);
//        }
//
//        @Bean
//        public Binding channelStatusBinding() {
//            return BindingBuilder.bind(channelStatusQueue())
//                    .to(channelStatusExchange())
//                    .with(env);
//        }
//    }

    @Configuration
    public static class SuccessBindingConfig {

        @Value("${spring.profiles.active}")
        private String env;

        @Bean
        public DirectExchange successExchange() {
            return new DirectExchange(EXCHANGE_SUCCESS, true, false);
        }

        @Bean
        public Queue successUserQueue() {
            return new Queue(QUEUE_MESSAGE_PERSIST + "_" + env, true);
        }

        @Bean
        public Binding successUserBinding() {
            return BindingBuilder.bind(successUserQueue())
                    .to(successExchange()).with(env);
        }
    }

    @Configuration
    public static class ErrorMessageBindingConfig {
        @Value("${spring.profiles.active}")
        private String env;

        @Bean
        public DirectExchange errorMessageExchange() {
            return new DirectExchange(EXCHANGE_ERROR_MESSAGE, true, false);
        }

        @Bean
        public Queue errorMessageQueue() {
            return new Queue(QUEUE_ERROR_MESSAGE + "_" + env, true);
        }

        @Bean
        public Binding errorMessageBinding() {
            return BindingBuilder.bind(errorMessageQueue())
                    .to(errorMessageExchange()).with(env);
        }
    }

    @Bean
    public RabbitTemplate rabbitTemplate(final ConnectionFactory connectionFactory, ObjectMapper objectMapper) {
        CachingConnectionFactory cachingConnectionFactory =  (CachingConnectionFactory) connectionFactory;
        cachingConnectionFactory.getRabbitConnectionFactory().setAutomaticRecoveryEnabled(true);

        final RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter(objectMapper));
        rabbitTemplate.setConfirmCallback(confirmCallback());
        return rabbitTemplate;
    }

    @Bean
    public RabbitTemplate.ConfirmCallback confirmCallback() {
        return (correlationData, ack, cause) -> {
            if (!ack) {
                log.error("rabbit call back " + cause);
            }
        };
    }




}
